import { QForm } from 'quasar';
import { UnwrapRef, nextTick, onMounted, ref } from 'vue';

import { Message, MessageBox, DEL_MESSAGE } from 'src/utils';
import { useTableServer } from './useTable';

export function useCrud<T>(api: CrudApi<T>, query: PageQuery = {} as PageQuery) {
  // 读取数据
  function handleRead(id: IdType, callBack: (data: T) => void) {
    api.readData(id).then((data) => callBack(data));
  }

  // 删除数据
  const handleDelete = (ids: IdType[], callBack: () => void, confirmMsg?: string, successMsg?: string | false) => {
    if (!ids || ids?.length === 0) {
      Message.warning('请先选择要删除的记录');
      return;
    }
    MessageBox.confirm(confirmMsg || DEL_MESSAGE, '警告').onOk(() =>
      api.deleteByIds(ids).then(() => {
        if (successMsg !== false) {
          Message.success(successMsg || '删除成功。');
        }
        callBack();
      }),
    );
  };

  // 导出
  const exportLoading = ref(false);
  function handleExport() {
    exportLoading.value = true;
    api.exportData(query!).finally(() => (exportLoading.value = false));
  }

  // 表单保存数据
  const formRef = ref<QForm>();
  const loading = ref(false);
  const handleSubmit = (dto: T, callBack: (data: T) => void) => {
    // 正在加载中，不允许在点击，防止重复提交
    if (loading.value) return;
    formRef.value?.validate().then((success: boolean) => {
      if (!success) return;
      loading.value = true;
      api
        .saveOrUpdate(dto)
        .then((data) => callBack(data as T))
        // 一秒后才允许在点，防止点的太快，执行多次
        .finally(() => setTimeout(() => (loading.value = false), 1000));
    });
  };

  return { handleRead, handleDelete, exportLoading, handleExport, formRef, loading, handleSubmit };
}

export function useCrudList<T>(api: CrudApi<T>, query: PageQuery, idField: string) {
  // table相关属性
  const { tableOptions, handleQuery, hasSelected, selectedIds, getRowIndex } = useTableServer(api.queryList, query, idField);
  // crud
  const { handleDelete: deleteAction, exportLoading, handleExport } = useCrud(api, query);

  // 删除数据
  const handleDelete = (id?: IdType, msg?: string) => {
    const ids = id ? [id] : selectedIds.value ?? [];
    deleteAction(ids, handleQuery, msg);
  };

  return { tableOptions, handleQuery, hasSelected, selectedIds, getRowIndex, handleDelete, exportLoading, handleExport };
}

/**
 * @param crudApi
 * @param mountedCallBack 加载数据后的回调(有传入props.id); 传入false不在页面加载时查询数据; true加载数据没有回调
 */
export function useCrudForm<T>(
  api: CrudApi<T>,
  defaultProps: Partial<T> = {},
  props: { readonly id?: IdType },
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  emit: (event: 'close' | 'after-save', ...args: any[]) => void,
  mountedCallBack: boolean | ((data: T) => void) = true,
) {
  const dto = ref<T>({ ...defaultProps } as T);

  const isNew = props.id === undefined || props.id === '';
  const isEdit = !isNew;

  const { handleRead, formRef, loading, handleSubmit: submitAction } = useCrud(api, {} as PageQuery);

  // 有传入ID时,页面加载时查询数据
  if (isEdit && mountedCallBack) {
    onMounted(() =>
      handleRead(props.id, (data) => {
        dto.value = data as UnwrapRef<T>;
        if (typeof mountedCallBack === 'function') {
          mountedCallBack(dto.value as T);
        }
      }),
    );
  }

  // 保存后是否立即关闭,不关闭时默认清空表单,可以继续填写保存
  const closeAfterSave = ref(true);
  const handleSubmit = () => {
    submitAction(dto.value as T, (data) => {
      emit('after-save', data);
      Message.success('保存成功');
      if (closeAfterSave.value) emit('close');
      else {
        if (isNew) {
          dto.value = { ...defaultProps } as UnwrapRef<T>;
          nextTick(() => formRef.value?.resetValidation());
        }
      }
    });
  };

  return { formRef, dto, closeAfterSave, loading, handleSubmit, submitAction, isNew, isEdit };
}
